package org.eclipse.epsilon.emc.jdt;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
import org.eclipse.jdt.core.dom.ArrayAccess;
import org.eclipse.jdt.core.dom.ArrayCreation;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.AssertStatement;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BlockComment;
import org.eclipse.jdt.core.dom.BooleanLiteral;
import org.eclipse.jdt.core.dom.BreakStatement;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.CharacterLiteral;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ConditionalExpression;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
import org.eclipse.jdt.core.dom.ContinueStatement;
import org.eclipse.jdt.core.dom.DoStatement;
import org.eclipse.jdt.core.dom.EmptyStatement;
import org.eclipse.jdt.core.dom.EnhancedForStatement;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ForStatement;
import org.eclipse.jdt.core.dom.IfStatement;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.Initializer;
import org.eclipse.jdt.core.dom.InstanceofExpression;
import org.eclipse.jdt.core.dom.LabeledStatement;
import org.eclipse.jdt.core.dom.LineComment;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.NullLiteral;
import org.eclipse.jdt.core.dom.NumberLiteral;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
import org.eclipse.jdt.core.dom.PostfixExpression;
import org.eclipse.jdt.core.dom.PrefixExpression;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.QualifiedType;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.SuperFieldAccess;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.SwitchCase;
import org.eclipse.jdt.core.dom.SwitchStatement;
import org.eclipse.jdt.core.dom.SynchronizedStatement;
import org.eclipse.jdt.core.dom.ThisExpression;
import org.eclipse.jdt.core.dom.ThrowStatement;
import org.eclipse.jdt.core.dom.TryStatement;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
import org.eclipse.jdt.core.dom.TypeLiteral;
import org.eclipse.jdt.core.dom.UnionType;
import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.WhileStatement;
import org.eclipse.jdt.core.dom.WildcardType;

/**
 * Manipulates Java source using JDT
 * @author Cheng Yun
 *
 */
public class JdtManipulator {
	IProject[] projects;
	
	/**
	 * Constructor: default 
	 */
	public JdtManipulator(){
		
	}
	
	/**
	 * Constructor: initialise the projects with the parameter passed in
	 * @param projects java projects to be manipulated
	 */
	public JdtManipulator(IProject[] projects){
		this.projects = projects;
	}

	/**
	 * Constructor: read all projects in the workspace
	 * @param str
	 */
	public JdtManipulator(String str) {
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		IWorkspaceRoot root = workspace.getRoot();
		// Get all projects in the workspace
		projects = root.getProjects();
	}
	
	/**
	 * returns all IProjects in the workspace
	 * 
	 * @return an array of IProject objects
	 */
	public static IProject [] getIProjects(){
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		IWorkspaceRoot root = workspace.getRoot();	
		//get all projects in the workspace
		IProject[] projects = root.getProjects();
		
		return projects;
	}
		
	/**
	 * Converts a IProject to IJavaProject if it has a java nature
	 * @param IProject
	 * @return IJavaProject
	 * @throws CoreException
	 */
	public static IJavaProject getIJavaProject(IProject project) throws CoreException{
		IJavaProject javaProject;
		//the project should be a open Java project
		if (project.isNatureEnabled("org.eclipse.jdt.core.javanature")&&project.isOpen()){
			javaProject = JavaCore.create(project);
			return javaProject;
		}
		return null;
	}
	
	/**
	 * Converts an array of IProject to an array of IJavaProject, skipping elements which are not of Java nature
	 * @param proejcts IProject []
	 * @return an array of IJavaProject AST nodes
	 * @throws CoreException
	 */
	public static IJavaProject [] getIJavaProjects(IProject [] proejcts) throws CoreException{
		List <IJavaProject> sourceProjects = new ArrayList<IJavaProject>();
		for(IProject project : proejcts){
			if(getIJavaProject(project)!= null){
				sourceProjects.add(getIJavaProject(project));
			}
		}
		IJavaProject [] javaProjects = sourceProjects.toArray(new IJavaProject[sourceProjects.size()]);
		
		return javaProjects;	
	}
	
	/**
	 * returns all packages that contains source code in a java project
	 * 
	 * @param javaProject
	 *            the javaProject to be parsed;
	 * @param isSource
	 *            if true,  return the java source packages only; otherwise, return all packages.
	 * @return an array of packages containing Java source
	 * @throws CoreException
	 */
	public static IPackageFragment[] getIPackageFragments(IJavaProject javaProject,
			boolean isSource) throws CoreException {
		if(javaProject != null){
			IPackageFragment[] packages = javaProject.getPackageFragments();
			List <IPackageFragment> sourcePackages = new ArrayList<IPackageFragment>();	
			if (isSource) {// only package containing source code should be returned
				for (IPackageFragment packageFragment : packages) {
					//if this is a java source package
					if (packageFragment.getKind() == IPackageFragmentRoot.K_SOURCE) {
						sourcePackages.add(packageFragment);
					}
				}
				packages = sourcePackages.toArray(new IPackageFragment[sourcePackages.size()]);
			}else {
				for (IPackageFragment packageFragment : packages) {
						if(packageFragment != null){
							sourcePackages.add(packageFragment);
						}
				}
				packages = sourcePackages.toArray(new IPackageFragment[sourcePackages.size()]);
			}

			return packages;
		}
		return null;
	}
	
	/**
	 * returns all packages that contains source code in the given java projects
	 * 
	 * @param javaProjects IPackageFragment[]
	 * @param isSource a flag indicating if the returned IPackageFragment should be
	 *            java source package only.
	 * @return
	 * @throws CoreException
	 */
	public static IPackageFragment[] getIPackageFragments(
			IJavaProject[] javaProjects, boolean isSource) throws CoreException {
		List<IPackageFragment> packageList = new ArrayList<IPackageFragment>();
		for (IJavaProject javaProject : javaProjects) {
			if (javaProject != null) {
				packageList.addAll(Arrays.asList(getIPackageFragments(
						javaProject, true)));
			}
		}
		IPackageFragment[] packages = packageList
				.toArray(new IPackageFragment[packageList.size()]);
		return packages;
	}

	/**
	 * returns all packages that contains source code in a java project
	 * 
	 * @param project
	 *            the IProject to be parsed;
	 * @param isSource
	 *            a flag indicating if the returned IPackageFragment should be
	 *            java source package only.
	 * @return an array of packages containing Java source
	 * @throws CoreException
	 */
	public static IPackageFragment[] getIPackageFragments(IProject project,
			boolean isSource) throws CoreException {
		if (project.hasNature("org.eclipse.jdt.core.javanature")) {
			IJavaProject javaProject = getIJavaProject(project);
			IPackageFragment[] packages = getIPackageFragments(javaProject,
					isSource);
			return packages;
		}

		return null;
	}	

	/**
	 * returns all ICompilationUnits in a package
	 * 
	 * @param packageFragment
	 * @return
	 * @throws JavaModelException
	 */
	public static ICompilationUnit[] getICompilationUnits(
		IPackageFragment packageFragment) throws JavaModelException {
		ICompilationUnit[] iUnit = null;
		// determine if it is a java source code package
		if (packageFragment.getKind() == IPackageFragmentRoot.K_SOURCE) {
			iUnit = packageFragment.getCompilationUnits();
		}
		return iUnit;
	}

	/**
	 * creates a AST tree based on the ICompilationUnit passed in
	 * 
	 * @param unit
	 * @return
	 */
	public static CompilationUnit parse(ICompilationUnit iUnit) {
		ASTParser parser = ASTParser.newParser(AST.JLS4);
		parser.setKind(ASTParser.K_COMPILATION_UNIT);
		parser.setSource(iUnit);
		parser.setResolveBindings(true);
		return (CompilationUnit) parser.createAST(null); // parse
	}
	
	/**
	 * return all CompilationUnits AST nodes of all the projects to be manipulated
	 * @return
	 * @throws CoreException
	 */
	public List <CompilationUnit> getCompilationUnits() throws CoreException {
		List <CompilationUnit> units = new ArrayList<CompilationUnit>();
		//traverse all project that are open
		for (IProject project : projects) {
			// determin if the project is open
			if (project.isOpen()) {
				if (project.hasNature("org.eclipse.jdt.core.javanature")){
					IJavaProject javaProject = getIJavaProject(project);
				IPackageFragment[] packageFragments = getIPackageFragments(javaProject,true);
				//traverse all package fragments
				for(IPackageFragment packageFragment : packageFragments	){
					ICompilationUnit [] iunit = getICompilationUnits (packageFragment);
					//traverse all ICompilationUnits
					for(int i=0; i<iunit.length;i++){
						units.add(parse(iunit[i]));
					}
				}
			}
			}
		}

		return units;
	}

	/**
	 * return all CompilationUnits AST nodes in the given package
	 * @return
	 * @throws CoreException
	 */
	public static CompilationUnit [] getCompilationUnits(IPackageFragment packageFragment) throws CoreException{
		if(packageFragment != null){
			ICompilationUnit [] iunit = getICompilationUnits (packageFragment);
			CompilationUnit [] units = new CompilationUnit[iunit.length];
			//traverse all ICompilationUnits
			for(int i=0; i<iunit.length;i++){
				units[i]=parse(iunit[i]);
			}
			return units;
		}
		return null;
	}
	
	/**
	 * return all CompilationUnits AST nodes in the given project
	 * 
	 * @param javaProject: An IJavaProject to be parsed
	 * @return a list of compilation units
	 * @throws CoreException
	 */
	public static List <CompilationUnit> getCompilationUnits(IJavaProject javaProject) throws CoreException {
		if(javaProject != null){
			List <CompilationUnit> units = new ArrayList<CompilationUnit>();
			for(IPackageFragment packageFragment : getIPackageFragments(javaProject,true)){
				for(CompilationUnit unit : getCompilationUnits(packageFragment)){
					units.add(unit);
				}
			}
			return units;
		}
		return null;
	}
	
	/**
	 * return all CompilationUnits AST nodes in the given project array
	 * 
	 * @param javaProject: An array of IJavaProjects to be parsed
	 * @return a list of CompilationUnit
	 * @throws CoreException
	 */
	public static List <CompilationUnit> getCompilationUnits(IJavaProject[] javaProjects) throws CoreException {
		List <CompilationUnit> units = new ArrayList<CompilationUnit>();
		for(IJavaProject javaProject: javaProjects){
			if(javaProject != null){
				units.addAll(getCompilationUnits(javaProject));
			}
		}
		return units;
	}
	
	/**
	 * returns the package declaration AST nodes to which the given
	 * compilation belongs
	 * 
	 * @param unit CompilationUnit
	 * @return PackageDeclaration
	 */
	public static PackageDeclaration getPackageDeclarations(CompilationUnit unit) {

		return unit.getPackage();
	}
	
	/**
	 * returns a list of class declaration AST nodes in the given compilation unit
	 * 
	 * @param unit CompilationUnit
	 * @return an array of TypeDeclaration
	 */
	public static TypeDeclaration[] getTypeDeclarations(CompilationUnit unit) {
		if(unit != null){
			Visitor cVisitor = new Visitor();
			unit.accept(cVisitor);
			TypeDeclaration[] classes = new TypeDeclaration[cVisitor
					.getClasses().size()];

			for (int i = 0; i < cVisitor.getClasses().size(); i++) {
				classes[i] = cVisitor.getClasses().get(i);
			}

			return classes;
		}
		return null;
	}
	
	/**
	 * returns a list of class declaration AST nodes in the given java project
	 * @param javaProject IJavaProject
	 * @return a list of TypeDeclaration
	 * @throws CoreException
	 */
	public static List<TypeDeclaration> getTypeDeclarations(IJavaProject javaProject) throws CoreException{
		if(javaProject!=null){
			List <TypeDeclaration> typeDeclarations = new ArrayList<TypeDeclaration>();
			for(CompilationUnit unit : getCompilationUnits(javaProject)){
				typeDeclarations.addAll(Arrays.asList(getTypeDeclarations(unit)));
			}
			return typeDeclarations;
		}

		return null;
	}
	
	/**
	 * returns a list of class declaration AST nodes in the given
	 * 
	 * @param javaProjects
	 * @return a list of TypeDeclaration
	 * @throws CoreException
	 */
	public static List<TypeDeclaration> getTypeDeclarations(IJavaProject [] javaProjects) throws CoreException{
		List <TypeDeclaration> typeDeclarations = new ArrayList<TypeDeclaration>();
		for(IJavaProject javaProject: javaProjects){
			if(javaProject != null){
				typeDeclarations.addAll(getTypeDeclarations(javaProject));
			}
		}
		return typeDeclarations;
	}

	/**
	 * returns a list containing the class declaration AST nodes in the given
	 * IPackageFragment
	 * @param packageFragment IPackageFragment
	 * @return a list containing the class declaration AST nodes
	 * @throws CoreException
	 */
	public static List<TypeDeclaration> getTypeDeclarations(IPackageFragment packageFragment) throws CoreException{
		if(packageFragment!=null){
			List <TypeDeclaration> typeDeclarations = new ArrayList<TypeDeclaration>();
			for(CompilationUnit unit : getCompilationUnits(packageFragment)){
				typeDeclarations.addAll(Arrays.asList(getTypeDeclarations(unit)));
			}
			return typeDeclarations;
		}

		return null;
	}
	
	/**
	 * returns a list of EnumDeclaration AST nodes in the given compilation unit
	 * 
	 * @param unit CompilationUnit
	 * @return an array of EnumDeclaration
	 */
	public static EnumDeclaration[] getEnumerations(CompilationUnit unit) {
		if(unit != null){
			Visitor cVisitor = new Visitor();
			unit.accept(cVisitor);
			EnumDeclaration[] enumerations = new EnumDeclaration[cVisitor
					.getEnumerations().size()];

			for (int i = 0; i < cVisitor.getClasses().size(); i++) {
				enumerations[i] = cVisitor.getEnumerations().get(i);
			}

			return enumerations;
		}
		return null;
	}
	
	/**
	 * returns a list of AnnotationTypeDeclaration AST nodes in the given compilation unit
	 * 
	 * @param unit CompilationUnit
	 * @return an array of AnnotationTypeDeclaration
	 */
	public static AnnotationTypeDeclaration[] getAnnotations(CompilationUnit unit) {
		if(unit != null){
			Visitor cVisitor = new Visitor();
			unit.accept(cVisitor);
			AnnotationTypeDeclaration[] annotations = new AnnotationTypeDeclaration[cVisitor
					.getAnnotations().size()];

			for (int i = 0; i < cVisitor.getClasses().size(); i++) {
				annotations[i] = cVisitor.getAnnotations().get(i);
			}

			return annotations;
		}
		return null;
	}
	
	/**
	 * returns a list of Initializer AST nodes in the given ASTNode 
	 * 
	 * @param node ASTNode
	 * @return an array of Initializer
	 */
	public static Initializer[] getInitializers(ASTNode node) {
		if(node != null){
			Visitor cVisitor = new Visitor();
			node.accept(cVisitor);
			Initializer[] initializers = new Initializer[cVisitor
					.getInitializers().size()];

			for (int i = 0; i < cVisitor.getClasses().size(); i++) {
				initializers[i] = cVisitor.getInitializers().get(i);
			}

			return initializers;
		}
		return null;
	}
	
	/**
	 * returns an array containing the FieldDeclaration AST nodes in the given
	 * TypeDeclaration
	 * 
	 * @param typeDeclaration TypeDeclaration
	 * @return an array of FieldDeclaration AST nodes
	 */
	public static FieldDeclaration[] getFieldDeclarations(TypeDeclaration typeDeclaration) {

		return typeDeclaration.getFields();
	}
	
	/**
	 * returns a list containing the ImportDeclaration AST nodes in the given
	 * CompilationUnit
	 * 
	 * @param unit CompilationUnit
	 * @return a list of ImportDeclaration AST nodes
	 */
	@SuppressWarnings("unchecked")
	public static List<ImportDeclaration> getImportDeclarations (CompilationUnit unit) {
		return unit.imports();
	}

	/**
	 * returns an list containing all the FieldDeclaration AST nodes in the
	 * given TypeDeclaration array
	 * 
	 * @param typeDeclaration
	 *            TypeDeclaration []
	 * @return an list of FieldDeclaration AST nodes
	 */
	public static List<FieldDeclaration> getFieldDeclarations(
			TypeDeclaration[] typeDeclarations) {
		List<FieldDeclaration> fields = new ArrayList<FieldDeclaration>();
		for (TypeDeclaration typeDeclaration : typeDeclarations) {
			fields.addAll(Arrays.asList(typeDeclaration.getFields()));
		}
		return fields;
	}
	
	/**
	 * returns an list containing all the FieldDeclaration AST nodes in the
	 * given IJavaProject AST node
	 * 
	 * @param javaProjects
	 *            IJavaProject
	 * @return an list of FieldDeclaration AST nodes
	 * @throws CoreException 
	 */
	public static List<FieldDeclaration> getFieldDeclarations(
			IJavaProject javaProject) throws CoreException {
		List<FieldDeclaration> fields = new ArrayList<FieldDeclaration>();
		for (TypeDeclaration typeDeclaration : getTypeDeclarations(javaProject)) {
			fields.addAll(Arrays.asList(typeDeclaration.getFields()));
		}
		return fields;
	}
	
	/**
	 * returns an list containing all the FieldDeclaration AST nodes in the
	 * given IJavaProject array
	 * 
	 * @param javaProjects
	 *            IJavaProject []
	 * @return an list of FieldDeclaration AST nodes
	 * @throws CoreException 
	 */
	public static List<FieldDeclaration> getFieldDeclarations(
			IJavaProject[] javaProjects) throws CoreException {
		List<FieldDeclaration> fields = new ArrayList<FieldDeclaration>();
		for (TypeDeclaration typeDeclaration : getTypeDeclarations(javaProjects)) {
			fields.addAll(Arrays.asList(typeDeclaration.getFields()));
		}
		return fields;
	}

	
	/**
	 * returns a list of method declaration AST nodes in the given
	 * compilation unit
	 * 
	 * @param unit CompilationUnit
	 * @return a list of method declaration AST nodes
	 */
	public static MethodDeclaration[] getMethodDeclarations(CompilationUnit unit) {
		Visitor mVisitor = new Visitor();
		unit.accept(mVisitor);
		MethodDeclaration[] methods = new MethodDeclaration[mVisitor
				.getMethods().size()];

		for (int i = 0; i < mVisitor.getMethods().size(); i++) {
			methods[i] = mVisitor.getMethods().get(i);
		}

		return methods;
	}
	
	/**
	 * returns a list of method declaration AST nodes in the given
	 * IPackageFragment
	 * 
	 * @param unit
	 * @return a list containing the method declaration AST nodes
	 * @throws CoreException
	 */
	public static List <MethodDeclaration> getMethodDeclarations(IPackageFragment packageFragment) throws CoreException {
		List <MethodDeclaration> methods = new ArrayList<MethodDeclaration>();
//      @Deprecated
//		for(CompilationUnit unit : getCompilationUnits(packageFragment)){
//			Visitor mVisitor = new Visitor();
//			unit.accept(mVisitor);
//			methods.addAll(mVisitor.getMethods());
//		}
		
		for(TypeDeclaration typeDeclaration : getTypeDeclarations(packageFragment)){
			methods.addAll(Arrays.asList(typeDeclaration.getMethods()));
		}

		return methods;
	}

	/**
	 * returns a list of method declaration AST nodes in the given IJavaProject
	 * 
	 * @param javaProject
	 *            IJavaProject
	 * @return a list of MethodDeclaration AST nodes
	 * @throws CoreException
	 */
	public static List<MethodDeclaration> getMethodDeclarations(
			IJavaProject javaProject) throws CoreException {
		List<MethodDeclaration> methods = new ArrayList<MethodDeclaration>();
		for (TypeDeclaration typeDeclaration : getTypeDeclarations(javaProject)) {
			methods.addAll(Arrays.asList(typeDeclaration.getMethods()));
		}
		return methods;

	}

	/**
	 * returns a list of method declaration AST nodes in the given IJavaProject array
	 * 
	 * @param javaProjects IJavaProject[]
	 * @return a list of MethodDeclaration AST nodes
	 * @throws CoreException
	 */
	public static List<MethodDeclaration> getMethodDeclarations(
			IJavaProject[] javaProjects) throws CoreException {
		List<MethodDeclaration> methods = new ArrayList<MethodDeclaration>();
		for (TypeDeclaration typeDeclaration : getTypeDeclarations(javaProjects)) {
			methods.addAll(Arrays.asList(typeDeclaration.getMethods()));
		}
		return methods;
	}
	
	/**
	 * returns a list containing the method declaration AST nodes in the given
	 * TypeDeclaration
	 * 
	 * @param typeDeclaration TypeDeclaration
	 * @return a list of method declaration AST nodes
	 */
	public static MethodDeclaration[] getMethodDeclarations(TypeDeclaration typeDeclaration) {

		return typeDeclaration.getMethods();
	}
	
	/**
	 * returns an array that contains all the variable declaration statement AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of VariableDeclarationFragment nodes
	 */
	public static VariableDeclarationStatement[] getVariableDeclarationStatements(
			ASTNode node) {
			Visitor vVisitor = new Visitor();
			node.accept(vVisitor);
			VariableDeclarationStatement[] variables = new VariableDeclarationStatement[vVisitor
					.getVariables().size()];
	
			for (int i = 0; i < variables.length; i++) {
				variables[i] = vVisitor.getVariables().get(i);
			}
			return variables;
	}
	
	/**
	 * returns an array that contains all ArrayType AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of ArrayType nodes
	 */
	public static ArrayType[] getArrayTypes(ASTNode node) {
			Visitor vVisitor = new Visitor();
			node.accept(vVisitor);
			ArrayType[] arrayTypes = new ArrayType[vVisitor
					.getArrayTypes().size()];
	
			for (int i = 0; i < arrayTypes.length; i++) {
				arrayTypes[i] = vVisitor.getArrayTypes().get(i);
			}
			return arrayTypes;
	}
	
	/**
	 * returns an array that contains all ParameterizedType AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of ParameterizedType nodes
	 */
	public static ParameterizedType[] getParameterizedTypes(
			ASTNode node) {
			Visitor vVisitor = new Visitor();
			node.accept(vVisitor);
			ParameterizedType[] parameterizedTypes = new ParameterizedType[vVisitor
					.getParameterizedTypes().size()];
	
			for (int i = 0; i < parameterizedTypes.length; i++) {
				parameterizedTypes[i] = vVisitor.getParameterizedTypes().get(i);
			}
			return parameterizedTypes;
	}
	
	/**
	 * returns an array that contains all PrimitiveType AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of PrimitiveType nodes
	 */
	public static PrimitiveType[] getPrimitiveTypes(
			ASTNode node) {
			Visitor vVisitor = new Visitor();
			node.accept(vVisitor);
			PrimitiveType[] primitiveTypes = new PrimitiveType[vVisitor
					.getPrimitiveTypes().size()];
	
			for (int i = 0; i < primitiveTypes.length; i++) {
				primitiveTypes[i] = vVisitor.getPrimitiveTypes().get(i);
			}
			return primitiveTypes;
	}
	
	/**
	 * returns an array that contains all QualifiedType AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of QualifiedType nodes
	 */
	public static QualifiedType[] getQualifiedTypes(
			ASTNode node) {
			Visitor vVisitor = new Visitor();
			node.accept(vVisitor);
			QualifiedType[] qualifiedTypes = new QualifiedType[vVisitor
					.getQualifiedTypes().size()];
	
			for (int i = 0; i < qualifiedTypes.length; i++) {
				qualifiedTypes[i] = vVisitor.getQualifiedTypes().get(i);
			}
			return qualifiedTypes;
	}
	
	/**
	 * returns an array that contains all SimpleType AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of SimpleType nodes
	 */
	public static SimpleType[] getSimpleTypes(
			ASTNode node) {
			Visitor vVisitor = new Visitor();
			node.accept(vVisitor);
			SimpleType[] simpleTypes = new SimpleType[vVisitor
					.getSimpleTypes().size()];
	
			for (int i = 0; i < simpleTypes.length; i++) {
				simpleTypes[i] = vVisitor.getSimpleTypes().get(i);
			}
			return simpleTypes;
	}
	
	/**
	 * returns an array that contains all UnionType AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of UnionType nodes
	 */
	public static UnionType[] getUnionTypes(
			ASTNode node) {
			Visitor vVisitor = new Visitor();
			node.accept(vVisitor);
			UnionType[] unionTypes = new UnionType[vVisitor
					.getUnionTypes().size()];
	
			for (int i = 0; i < unionTypes.length; i++) {
				unionTypes[i] = vVisitor.getUnionTypes().get(i);
			}
			return unionTypes;
	}

	/**
	 * returns an array that contains all WildcardType AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of WildcardType nodes
	 */
	public static WildcardType[] getWildcardTypes(
			ASTNode node) {
			Visitor vVisitor = new Visitor();
			node.accept(vVisitor);
			WildcardType[] wildcardTypes = new WildcardType[vVisitor
					.getWildcardTypes().size()];
	
			for (int i = 0; i < wildcardTypes.length; i++) {
				wildcardTypes[i] = vVisitor.getWildcardTypes().get(i);
			}
			return wildcardTypes;
	}

	/**
	 * returns an array that contains all the variable declaration statement AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param methodDeclaration MethodDeclaration
	 * @return an array of VariableDeclarationFragment nodes
	 */
	public static VariableDeclarationStatement[] getVariableDeclarationStatements(
			MethodDeclaration methodDeclaration) {
			Visitor vVisitor = new Visitor();
			methodDeclaration.accept(vVisitor);
			VariableDeclarationStatement[] variables = new VariableDeclarationStatement[vVisitor
					.getVariables().size()];
	
			for (int i = 0; i < variables.length; i++) {
				variables[i] = vVisitor.getVariables().get(i);
			}
			return variables;
	}
	
	/**
	 * returns an array that contains all the IfStatement AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of IfStatement nodes
	 */
	public static IfStatement [] getIfStatements(MethodDeclaration methodDeclaration){
		Visitor iVisitor = new Visitor();
		methodDeclaration.accept(iVisitor);
		IfStatement[] ifStatements = new IfStatement[iVisitor
				.getIfStatements().size()];
		for (int i = 0; i < ifStatements.length; i++) {
			ifStatements[i] = iVisitor.getIfStatements().get(i);
		}
		return ifStatements;
	}
	
	/**
	 * returns an array that contains all the IfStatement AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of IfStatement nodes
	 */
	public static  IfStatement [] getIfStatements(ASTNode node) {
		Visitor iVisitor = new Visitor();
		node.accept(iVisitor);
		IfStatement[] ifStatements = new IfStatement[iVisitor
				.getIfStatements().size()];
		for (int i = 0; i < ifStatements.length; i++) {
			ifStatements[i] = iVisitor.getIfStatements().get(i);
		}
		return ifStatements;
	}
	
	/**
	 * returns an array that contains all the WhileStatement AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of WhileStatement nodes
	 */
	public static WhileStatement [] getWhileStatements(MethodDeclaration methodDeclaration){
		Visitor wVisitor = new Visitor();
		methodDeclaration.accept(wVisitor);
		WhileStatement[] whileStatements = new WhileStatement[wVisitor
				.getWhileStatements().size()];
		for (int i = 0; i < whileStatements.length; i++) {
			whileStatements[i] = wVisitor.getWhileStatements().get(i);
		}
		return whileStatements;
	}
	
	/**
	 * returns an array that contains all the WhileStatement AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of WhileStatement nodes
	 */
	public static WhileStatement [] getWhileStatements(ASTNode node){
		Visitor wVisitor = new Visitor();
		node.accept(wVisitor);
		WhileStatement[] whileStatements = new WhileStatement[wVisitor
				.getWhileStatements().size()];
		for (int i = 0; i < whileStatements.length; i++) {
			whileStatements[i] = wVisitor.getWhileStatements().get(i);
		}
		return whileStatements;
	}
	
	/**
	 * returns an array that contains all the DoStatement AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of DoStatement nodes
	 */
	public static DoStatement [] getDoStatements(MethodDeclaration methodDeclaration){
		Visitor dVisitor = new Visitor();
		methodDeclaration.accept(dVisitor);
		DoStatement[] doStatements = new DoStatement[dVisitor
				.getDoStatements().size()];
		for (int i = 0; i < doStatements.length; i++) {
			doStatements[i] = dVisitor.getDoStatements().get(i);
		}
		return doStatements;
	}

	/**
	 * returns an array that contains all the DoStatement AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of DoStatement nodes
	 */
	public static DoStatement [] getDoStatements(ASTNode node){
		Visitor dVisitor = new Visitor();
		node.accept(dVisitor);
		DoStatement[] doStatements = new DoStatement[dVisitor
				.getDoStatements().size()];
		for (int i = 0; i < doStatements.length; i++) {
			doStatements[i] = dVisitor.getDoStatements().get(i);
		}
		return doStatements;
	}
	
	/**
	 * returns an array that contains all the SwitchStatement AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of SwitchStatement nodes
	 */
	public static SwitchStatement [] getSwitchStatements(MethodDeclaration methodDeclaration){
		Visitor sVisitor = new Visitor();
		methodDeclaration.accept(sVisitor);
		SwitchStatement[] switchStatements = new SwitchStatement[sVisitor
				.getSwitchStatements().size()];
		for (int i = 0; i < switchStatements.length; i++) {
			switchStatements[i] = sVisitor.getSwitchStatements().get(i);
		}
		return switchStatements;
	}
		
	/**
	 * returns an array that contains all the SwitchStatement AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of SwitchStatement nodes
	 */
	public static SwitchStatement [] getSwitchStatements(ASTNode node){
		Visitor sVisitor = new Visitor();
		node.accept(sVisitor);
		SwitchStatement[] switchStatements = new SwitchStatement[sVisitor
				.getSwitchStatements().size()];
		for (int i = 0; i < switchStatements.length; i++) {
			switchStatements[i] = sVisitor.getSwitchStatements().get(i);
		}
		return switchStatements;
	}
	
	/**
	 * returns an array that contains all the ForStatement AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of ForStatement nodes
	 */
	public static ForStatement[] getForStatements(MethodDeclaration method) {
		Visitor fVisitor = new Visitor();
		method.accept(fVisitor);
		ForStatement[] forStatements = new ForStatement[fVisitor
				.getForStatements().size()];
		for (int i = 0; i < forStatements.length; i++) {
			forStatements[i] = fVisitor.getForStatements().get(i);
		}
		return forStatements;
	}
	
	/**
	 * returns an array that contains all the ForStatement AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of ForStatement nodes
	 */
	public static ForStatement[] getForStatements(ASTNode node) {
		Visitor fVisitor = new Visitor();
		node.accept(fVisitor);
		ForStatement[] forStatements = new ForStatement[fVisitor
				.getForStatements().size()];
		for (int i = 0; i < forStatements.length; i++) {
			forStatements[i] = fVisitor.getForStatements().get(i);
		}
		return forStatements;
	}

	/**
	 * returns an array that contains all the EnhancedForStatement AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of EnhancedForStatement nodes
	 */
	public static EnhancedForStatement[] getEnhancedForStatements(MethodDeclaration method) {
		Visitor efVisitor = new Visitor();
		method.accept(efVisitor);
		EnhancedForStatement[] enhancedForStatements = new EnhancedForStatement[efVisitor
				.getEnhancedForStatements().size()];
		for (int i = 0; i < enhancedForStatements.length; i++) {
			enhancedForStatements[i] = efVisitor.getEnhancedForStatements().get(i);
		}
		return enhancedForStatements;
	}
	
	/**
	 * returns an array that contains all the EnhancedForStatement AST nodes in
	 * the given ASTNode
	 * 
	 * @param node
	 *            ASTNode
	 * @return an array of EnhancedForStatement nodes
	 */
	public static EnhancedForStatement[] getEnhancedForStatements(ASTNode node) {
		Visitor efVisitor = new Visitor();
		node.accept(efVisitor);
		EnhancedForStatement[] enhancedForStatements = new EnhancedForStatement[efVisitor
				.getEnhancedForStatements().size()];
		System.out.println(efVisitor.getEnhancedForStatements().size());

		for (int i = 0; i < enhancedForStatements.length; i++) {
			enhancedForStatements[i] = efVisitor.getEnhancedForStatements()
					.get(i);
		}
		return enhancedForStatements;
	}
	
	/**
	 * returns an array that contains all the TryStatement AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of TryStatement nodes
	 */
	public static TryStatement[] getTryStatements(MethodDeclaration method) {
		Visitor tVisitor = new Visitor();
		method.accept(tVisitor);
		TryStatement[] tryStatements = new TryStatement[tVisitor
				.getTryStatements().size()];
		for (int i = 0; i < tryStatements.length; i++) {
			tryStatements[i] = tVisitor.getTryStatements().get(i);
		}
		return tryStatements;
	}
	
	/**
	 * returns an array that contains all the TryStatement AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of TryStatement nodes
	 */
	public static TryStatement[] getTryStatements(ASTNode node) {
		Visitor tVisitor = new Visitor();
		node.accept(tVisitor);
		TryStatement[] tryStatements = new TryStatement[tVisitor
				.getTryStatements().size()];
		for (int i = 0; i < tryStatements.length; i++) {
			tryStatements[i] = tVisitor.getTryStatements().get(i);
		}
		return tryStatements;
	}
	
	/**
	 * returns an array that contains all the SynchronizedStatement AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of SynchronizedStatement nodes
	 */
	public static SynchronizedStatement[] getSynchronizedStatements(MethodDeclaration method) {
		Visitor sVisitor = new Visitor();
		method.accept(sVisitor);
		SynchronizedStatement[] synchronizedStatements = new SynchronizedStatement[sVisitor
				.getSynchronizedStatements().size()];
		for (int i = 0; i < synchronizedStatements.length; i++) {
			synchronizedStatements[i] = sVisitor.getSynchronizedStatements().get(i);
		}
		return synchronizedStatements;
	}
	
	/**
	 * returns an array that contains all the SynchronizedStatement AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of SynchronizedStatement nodes
	 */
	public static SynchronizedStatement[] getSynchronizedStatements(ASTNode node) {
		Visitor sVisitor = new Visitor();
		node.accept(sVisitor);
		SynchronizedStatement[] synchronizedStatements = new SynchronizedStatement[sVisitor
				.getSynchronizedStatements().size()];
		for (int i = 0; i < synchronizedStatements.length; i++) {
			synchronizedStatements[i] = sVisitor.getSynchronizedStatements().get(i);
		}
		return synchronizedStatements;
	}
	
	/**
	 * returns an array that contains all the AssertStatement AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of AssertStatement nodes
	 */
	public static AssertStatement[] getAssertStatements(ASTNode node) {
		Visitor sVisitor = new Visitor();
		node.accept(sVisitor);
		AssertStatement[] assertStatements = new AssertStatement[sVisitor
				.getAssertStatements().size()];
		for (int i = 0; i < assertStatements.length; i++) {
			assertStatements[i] = sVisitor.getAssertStatements().get(i);
		}
		return assertStatements;
	}
	
	/**
	 * returns an array that contains all the ThrowStatement AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of ThrowStatement nodes
	 */
	public static ThrowStatement[] getThrowStatements(ASTNode node) {
		Visitor sVisitor = new Visitor();
		node.accept(sVisitor);
		ThrowStatement[] throwStatements = new ThrowStatement[sVisitor
				.getThrowStatements().size()];
		for (int i = 0; i < throwStatements.length; i++) {
			throwStatements[i] = sVisitor.getThrowStatements().get(i);
		}
		return throwStatements;
	}
	
	/**
	 * returns an array that contains all the TypeDeclarationStatement AST nodes in
	 * the CompilationUnit ASTNode
	 * 
	 * @param unit CompilationUnit
	 * @return a TypeDeclarationStatement node
	 */
	public static TypeDeclarationStatement[] getTypeDeclarationStatements(
			CompilationUnit unit) {
		Visitor sVisitor = new Visitor();
		unit.accept(sVisitor);
		TypeDeclarationStatement[] typeDeclarationStatements = new TypeDeclarationStatement[sVisitor
				.getTypeDeclarationStatements().size()];
		System.out.println(typeDeclarationStatements.length);
		for (int i = 0; i < typeDeclarationStatements.length; i++) {
			typeDeclarationStatements[i] = sVisitor
					.getTypeDeclarationStatements().get(i);
		}
		return typeDeclarationStatements;
	}

	/**
	 * returns an array that contains all the SwitchCase AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of SwitchCase nodes
	 */
	public static SwitchCase[] getSwitchCases(ASTNode node) {
		Visitor sVisitor = new Visitor();
		node.accept(sVisitor);
		SwitchCase[] switchCases = new SwitchCase[sVisitor
				.getSwitchCases().size()];
		for (int i = 0; i < switchCases.length; i++) {
			switchCases[i] = sVisitor.getSwitchCases().get(i);
		}
		return switchCases;
	}
	
	/**
	 * returns an array that contains all the Block AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of Block nodes
	 */
	public static Block[] getBlocks(ASTNode node) {
		Visitor sVisitor = new Visitor();
		node.accept(sVisitor);
		Block[] blocks = new Block[sVisitor
				.getBlocks().size()];
		for (int i = 0; i < blocks.length; i++) {
			blocks[i] = sVisitor.getBlocks().get(i);
		}
		return blocks;
	}
	
	/**
	 * returns an array that contains all the BreakStatement AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of BreakStatement nodes
	 */
	public static BreakStatement[] getBreakStatements(ASTNode node) {
		Visitor sVisitor = new Visitor();
		node.accept(sVisitor);
		BreakStatement[] breakStatements = new BreakStatement[sVisitor
				.getBreakStatements().size()];
		for (int i = 0; i < breakStatements.length; i++) {
			breakStatements[i] = sVisitor.getBreakStatements().get(i);
		}
		return breakStatements;
	}
	
	/**
	 * returns an array that contains all the ContinueStatement AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of ContinueStatement nodes
	 */
	public static ContinueStatement[] getContinueStatements(ASTNode node) {
		Visitor sVisitor = new Visitor();
		node.accept(sVisitor);
		ContinueStatement[] continueStatements = new ContinueStatement[sVisitor
				.getContinueStatements().size()];
		for (int i = 0; i < continueStatements.length; i++) {
			continueStatements[i] = sVisitor.getContinueStatements().get(i);
		}
		return continueStatements;
	}
	
	/**
	 * returns an array that contains all the ConstructorInvocation AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of ConstructorInvocation nodes
	 */
	public static ConstructorInvocation[] getConstructorInvocations(ASTNode node) {
		Visitor sVisitor = new Visitor();
		node.accept(sVisitor);
		ConstructorInvocation[] constructorInvocations = new ConstructorInvocation[sVisitor
				.getConstructorInvocations().size()];
		for (int i = 0; i < constructorInvocations.length; i++) {
			constructorInvocations[i] = sVisitor.getConstructorInvocations().get(i);
		}
		return constructorInvocations;
	}
	
	/**
	 * returns an array that contains all the EmptyStatement AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of EmptyStatement nodes
	 */
	public static EmptyStatement[] getEmptyStatements(ASTNode node) {
		Visitor sVisitor = new Visitor();
		node.accept(sVisitor);
		EmptyStatement[] emptyStatements = new EmptyStatement[sVisitor
				.getEmptyStatements().size()];
		for (int i = 0; i < emptyStatements.length; i++) {
			emptyStatements[i] = sVisitor.getEmptyStatements().get(i);
		}
		return emptyStatements;
	}
	
	/**
	 * returns an array that contains all the SuperConstructorInvocation AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of SuperConstructorInvocation nodes
	 */
	public static SuperConstructorInvocation[] getSuperConstructorInvocations(ASTNode node) {
		Visitor sVisitor = new Visitor();
		node.accept(sVisitor);
		SuperConstructorInvocation[] superConstructorInvocations = new SuperConstructorInvocation[sVisitor
				.getSuperConstructorInvocations().size()];
		for (int i = 0; i < superConstructorInvocations.length; i++) {
			superConstructorInvocations[i] = sVisitor.getSuperConstructorInvocations().get(i);
		}
		return superConstructorInvocations;
	}
	
	/**
	 * returns an array that contains all the LabeledStatement AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of LabeledStatement nodes
	 */
	public static LabeledStatement[] getLabeledStatements(ASTNode node) {
		Visitor sVisitor = new Visitor();
		node.accept(sVisitor);
		LabeledStatement[] labeledStatements = new LabeledStatement[sVisitor
				.getLabeledStatements().size()];
		for (int i = 0; i < labeledStatements.length; i++) {
			labeledStatements[i] = sVisitor.getLabeledStatements().get(i);
		}
		return labeledStatements;
	}
	
	/**
	 * returns an array that contains all the MethodInvocation AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of MethodInvocation nodes
	 */
	public static MethodInvocation[] getMethodInvocations(MethodDeclaration method){
		Visitor miVisitor = new Visitor();
		method.accept(miVisitor);
		MethodInvocation[] methodInvocations = new MethodInvocation[miVisitor
				.getMethodInvocations().size()];
		for (int i = 0; i < methodInvocations.length; i++) {
			methodInvocations[i] = miVisitor.getMethodInvocations().get(i);
		}
		return methodInvocations;
	}
	
	
	/**
	 * returns an array that contains all the MethodInvocation AST nodes in
	 * the given node node
	 * 
	 * @param node ASTNode
	 * @return an array of MethodInvocation nodes
	 */
	public static MethodInvocation[] getMethodInvocations(ASTNode node){
		Visitor miVisitor = new Visitor();
		node.accept(miVisitor);
		MethodInvocation[] methodInvocations = new MethodInvocation[miVisitor
				.getMethodInvocations().size()];
		for (int i = 0; i < methodInvocations.length; i++) {
			methodInvocations[i] = miVisitor.getMethodInvocations().get(i);
		}
		return methodInvocations;
	}
	
	/**
	 * returns an array that contains all the ExpressionStatement AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of ExpressionStatement nodes
	 */
	public static ExpressionStatement[] getExpressionStatements(MethodDeclaration method){
		Visitor rVisitor = new Visitor();
		method.accept(rVisitor);
		ExpressionStatement[] expressionStatements = new ExpressionStatement[rVisitor
				.getExpressionStatements().size()];
		for (int i = 0; i < expressionStatements.length; i++) {
			expressionStatements[i] = rVisitor.getExpressionStatements().get(i);
		}
		return expressionStatements;		
	}
	
	/**
	 * returns an array that contains all the ExpressionStatement AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of ExpressionStatement nodes
	 */
	public static ExpressionStatement[] getExpressionStatements(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		ExpressionStatement[] expressionStatements = new ExpressionStatement[rVisitor
				.getExpressionStatements().size()];
		for (int i = 0; i < expressionStatements.length; i++) {
			expressionStatements[i] = rVisitor.getExpressionStatements().get(i);
		}
		return expressionStatements;		
	}
	
	//getters of Expressions
	/**
	 * returns an array that contains all the StringLiteral AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of StringLiteral nodes
	 */
	public static StringLiteral[] getStringLiterals(MethodDeclaration method){
		Visitor rVisitor = new Visitor();
		method.accept(rVisitor);
		StringLiteral[] stringLiterals = new StringLiteral[rVisitor
				.getStringLiterals().size()];
		for (int i = 0; i < stringLiterals.length; i++) {
			stringLiterals[i] = rVisitor.getStringLiterals().get(i);
		}
		return stringLiterals;		
	}
	
	/**
	 * returns an array that contains all the StringLiteral AST nodes in
	 * the given ASTNode
	 * 
	 * @param node ASTNode
	 * @return an array of StringLiteral nodes
	 */
	public static StringLiteral[] getStringLiterals(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		StringLiteral[] stringLiterals = new StringLiteral[rVisitor
				.getStringLiterals().size()];
		for (int i = 0; i < stringLiterals.length; i++) {
			stringLiterals[i] = rVisitor.getStringLiterals().get(i);
		}
		return stringLiterals;		
	}
	
	/**
	 * returns an array that contains all the TypeLiteral AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of TypeLiteral nodes
	 */
	public static TypeLiteral[] getTypeLiterals(MethodDeclaration method){
		Visitor rVisitor = new Visitor();
		method.accept(rVisitor);
		TypeLiteral[] typeLiterals = new TypeLiteral[rVisitor
				.getTypeLiterals().size()];
		for (int i = 0; i < typeLiterals.length; i++) {
			typeLiterals[i] = rVisitor.getTypeLiterals().get(i);
		}
		return typeLiterals;		
	}
	
	/**
	 * returns an array that contains all the TypeLiteral AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of TypeLiteral nodes
	 */
	public static TypeLiteral[] getTypeLiterals(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		TypeLiteral[] typeLiterals = new TypeLiteral[rVisitor
				.getTypeLiterals().size()];
		for (int i = 0; i < typeLiterals.length; i++) {
			typeLiterals[i] = rVisitor.getTypeLiterals().get(i);
		}
		return typeLiterals;		
	}
	
	/**
	 * returns an array that contains all the NullLiteral AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of NullLiteral nodes
	 */
	public static NullLiteral[] getNullLiterals(MethodDeclaration method){
		Visitor rVisitor = new Visitor();
		method.accept(rVisitor);
		NullLiteral[] nullLiterals = new NullLiteral[rVisitor
				.getNullLiterals().size()];
		for (int i = 0; i < nullLiterals.length; i++) {
			nullLiterals[i] = rVisitor.getNullLiterals().get(i);
		}
		return nullLiterals;		
	}
	
	/**
	 * returns an array that contains all the NullLiteral AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of NullLiteral nodes
	 */
	public static NullLiteral[] getNullLiterals(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		NullLiteral[] nullLiterals = new NullLiteral[rVisitor
				.getNullLiterals().size()];
		for (int i = 0; i < nullLiterals.length; i++) {
			nullLiterals[i] = rVisitor.getNullLiterals().get(i);
		}
		return nullLiterals;		
	}
	
	/**
	 * returns an array that contains all the InfixExpression AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of InfixExpression nodes
	 */
	public static InfixExpression[] getInfixExpressions(MethodDeclaration method){
		Visitor rVisitor = new Visitor();
		method.accept(rVisitor);
		InfixExpression[] infixExpressions = new InfixExpression[rVisitor
				.getInfixExpressions().size()];
		for (int i = 0; i < infixExpressions.length; i++) {
			infixExpressions[i] = rVisitor.getInfixExpressions().get(i);
		}
		return infixExpressions;		
	}
	
	/**
	 * returns an array that contains all the InfixExpression AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of InfixExpression nodes
	 */
	public static InfixExpression[] getInfixExpressions(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		InfixExpression[] infixExpressions = new InfixExpression[rVisitor
				.getInfixExpressions().size()];
		for (int i = 0; i < infixExpressions.length; i++) {
			infixExpressions[i] = rVisitor.getInfixExpressions().get(i);
		}
		return infixExpressions;		
	}
	
	/**
	 * returns an array that contains all the ArrayAccess AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of ArrayAccess nodes
	 */
	public static ArrayAccess[] getArrayAccesses(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		ArrayAccess[] arrayAccesses = new ArrayAccess[rVisitor
				.getArrayAccesses().size()];
		for (int i = 0; i < arrayAccesses.length; i++) {
			arrayAccesses[i] = rVisitor.getArrayAccesses().get(i);
		}
		return arrayAccesses;		
	}
	
	/**
	 * returns an array that contains all the ArrayCreation AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of ArrayCreation nodes
	 */
	public static ArrayCreation[] getArrayCreations(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		ArrayCreation[] arrayCreations = new ArrayCreation[rVisitor
				.getArrayCreations().size()];
		for (int i = 0; i < arrayCreations.length; i++) {
			arrayCreations[i] = rVisitor.getArrayCreations().get(i);
		}
		return arrayCreations;		
	}
	
	/**
	 * returns an array that contains all the ArrayInitializer AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of ArrayInitializer nodes
	 */
	public static ArrayInitializer[] getArrayInitializers(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		ArrayInitializer[] arrayInitializers = new ArrayInitializer[rVisitor
				.getArrayInitializers().size()];
		for (int i = 0; i < arrayInitializers.length; i++) {
			arrayInitializers[i] = rVisitor.getArrayInitializers().get(i);
		}
		return arrayInitializers;		
	}
	
	
	/**
	 * returns an array that contains all the Assignment AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of Assignment nodes
	 */
	public static Assignment[] getAssignments(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		Assignment[] assignments = new Assignment[rVisitor
				.getAssignments().size()];
		for (int i = 0; i < assignments.length; i++) {
			assignments[i] = rVisitor.getAssignments().get(i);
		}
		return assignments;		
	}
	
	/**
	 * returns an array that contains all the BooleanLiteral AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of BooleanLiteral nodes
	 */
	public static BooleanLiteral[] getBooleanLiterals(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		BooleanLiteral[] booleanLiterals = new BooleanLiteral[rVisitor
				.getBooleanLiterals().size()];
		for (int i = 0; i < booleanLiterals.length; i++) {
			booleanLiterals[i] = rVisitor.getBooleanLiterals().get(i);
		}
		return booleanLiterals;		
	}
	
	/**
	 * returns an array that contains all the CastExpression AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of CastExpression nodes
	 */
	public static CastExpression[] getCastExpressions(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		CastExpression[] castExpressions = new CastExpression[rVisitor
				.getCastExpressions().size()];
		for (int i = 0; i < castExpressions.length; i++) {
			castExpressions[i] = rVisitor.getCastExpressions().get(i);
		}
		return castExpressions;		
	}
	
	/**
	 * returns an array that contains all the CharacterLiteral AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of CharacterLiteral nodes
	 */
	public static CharacterLiteral[] getCharacterLiterals(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		CharacterLiteral[] characterLiterals = new CharacterLiteral[rVisitor
				.getCharacterLiterals().size()];
		for (int i = 0; i < characterLiterals.length; i++) {
			characterLiterals[i] = rVisitor.getCharacterLiterals().get(i);
		}
		return characterLiterals;		
	}
	
	/**
	 * returns an array that contains all the ClassInstanceCreation AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of ClassInstanceCreation nodes
	 */
	public static ClassInstanceCreation[] getClassInstanceCreations(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		ClassInstanceCreation[] classInstanceCreations = new ClassInstanceCreation[rVisitor
				.getClassInstanceCreations().size()];
		for (int i = 0; i < classInstanceCreations.length; i++) {
			classInstanceCreations[i] = rVisitor.getClassInstanceCreations().get(i);
		}
		return classInstanceCreations;		
	}
	
	/**
	 * returns an array that contains all the ConditionalExpression AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of ConditionalExpression nodes
	 */
	public static ConditionalExpression[] getConditionalExpressions(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		ConditionalExpression[] conditionalExpressions = new ConditionalExpression[rVisitor
				.getConditionalExpressions().size()];
		for (int i = 0; i < conditionalExpressions.length; i++) {
			conditionalExpressions[i] = rVisitor.getConditionalExpressions().get(i);
		}
		return conditionalExpressions;		
	}
	
	/**
	 * returns an array that contains all the FieldAccess AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of FieldAccess nodes
	 */
	public static FieldAccess[] getFieldAccesses(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		FieldAccess[] fieldAccesses = new FieldAccess[rVisitor
				.getFieldAccesses().size()];
		for (int i = 0; i < fieldAccesses.length; i++) {
			fieldAccesses[i] = rVisitor.getFieldAccesses().get(i);
		}
		return fieldAccesses;		
	}
	
	/**
	 * returns an array that contains all the InstanceofExpression AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of InstanceofExpression nodes
	 */
	public static InstanceofExpression[] getInstanceofExpressions(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		InstanceofExpression[] instanceofExpressions = new InstanceofExpression[rVisitor
				.getInstanceofExpressions().size()];
		for (int i = 0; i < instanceofExpressions.length; i++) {
			instanceofExpressions[i] = rVisitor.getInstanceofExpressions().get(i);
		}
		return instanceofExpressions;		
	}
	
	/**3.
	 * returns an array that contains all the NumberLiteral AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of NumberLiteral nodes
	 */
	public static NumberLiteral[] getNumberLiterals(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		NumberLiteral[] numberLiterals = new NumberLiteral[rVisitor
				.getNumberLiterals().size()];
		for (int i = 0; i < numberLiterals.length; i++) {
			numberLiterals[i] = rVisitor.getNumberLiterals().get(i);
		}
		return numberLiterals;		
	}
	
	/**
	 * returns an array that contains all the ParenthesizedExpression AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of ParenthesizedExpression nodes
	 */
	public static ParenthesizedExpression[] getParenthesizedExpressions(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		ParenthesizedExpression[] parenthesizedExpressions = new ParenthesizedExpression[rVisitor
				.getParenthesizedExpressions().size()];
		for (int i = 0; i < parenthesizedExpressions.length; i++) {
			parenthesizedExpressions[i] = rVisitor.getParenthesizedExpressions().get(i);
		}
		return parenthesizedExpressions;		
	}
	
	/**
	 * returns an array that contains all the PostfixExpression AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of PostfixExpression nodes
	 */
	public static PostfixExpression[] getPostfixExpressions(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		PostfixExpression[] postfixExpressions = new PostfixExpression[rVisitor
				.getPostfixExpressions().size()];
		for (int i = 0; i < postfixExpressions.length; i++) {
			postfixExpressions[i] = rVisitor.getPostfixExpressions().get(i);
		}
		return postfixExpressions;		
	}
	
	/**
	 * returns an array that contains all the PrefixExpression AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of PrefixExpression nodes
	 */
	public static PrefixExpression[] getPrefixExpressions(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		PrefixExpression[] prefixExpressions = new PrefixExpression[rVisitor
				.getPrefixExpressions().size()];
		for (int i = 0; i < prefixExpressions.length; i++) {
			prefixExpressions[i] = rVisitor.getPrefixExpressions().get(i);
		}
		return prefixExpressions;		
	}
	
	/**
	 * returns an array that contains all the SuperFieldAccess AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of SuperFieldAccess nodes
	 */
	public static SuperFieldAccess[] getSuperFieldAccesses(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		SuperFieldAccess[] superFieldAccesses = new SuperFieldAccess[rVisitor
				.getSuperFieldAccesses().size()];
		for (int i = 0; i < superFieldAccesses.length; i++) {
			superFieldAccesses[i] = rVisitor.getSuperFieldAccesses().get(i);
		}
		return superFieldAccesses;		
	}
	
	/**
	 * returns an array that contains all the QualifiedName AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of QualifiedName nodes
	 */
	public static QualifiedName[] getQualifiedNames(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		QualifiedName[] qualifiedNames = new QualifiedName[rVisitor
				.getQualifiedNames().size()];
		for (int i = 0; i < qualifiedNames.length; i++) {
			qualifiedNames[i] = rVisitor.getQualifiedNames().get(i);
		}
		return qualifiedNames;		
	}
	
	/**
	 * returns an array that contains all the SimpleName AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of SimpleName nodes
	 */
	public static SimpleName[] getSimpleNames(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		SimpleName[] simpleNames = new SimpleName[rVisitor
				.getSimpleNames().size()];
		for (int i = 0; i < simpleNames.length; i++) {
			simpleNames[i] = rVisitor.getSimpleNames().get(i);
		}
		return simpleNames;		
	}
	
	/**
	 * returns an array that contains all the SuperMethodInvocation AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of SuperMethodInvocation nodes
	 */
	public static SuperMethodInvocation[] getSuperMethodInvocations(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		SuperMethodInvocation[] superMethodInvocations = new SuperMethodInvocation[rVisitor
				.getSuperMethodInvocations().size()];
		for (int i = 0; i < superMethodInvocations.length; i++) {
			superMethodInvocations[i] = rVisitor.getSuperMethodInvocations().get(i);
		}
		return superMethodInvocations;		
	}
	
	/**
	 * returns an array that contains all the ThisExpression AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of ThisExpression nodes
	 */
	public static ThisExpression[] getThisExpressions(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		ThisExpression[] thisExpressions = new ThisExpression[rVisitor
				.getThisExpressions().size()];
		for (int i = 0; i < thisExpressions.length; i++) {
			thisExpressions[i] = rVisitor.getThisExpressions().get(i);
		}
		return thisExpressions;		
	}
	
	/**
	 * returns an array that contains all the VariableDeclarationExpression AST nodes in
	 * the given ASTNode node
	 * 
	 * @param node ASTNode
	 * @return an array of VariableDeclarationExpression nodes
	 */
	public static VariableDeclarationExpression[] getVariableDeclarationExpressions(ASTNode node){
		Visitor rVisitor = new Visitor();
		node.accept(rVisitor);
		VariableDeclarationExpression[] variableDeclarationExpressions = new VariableDeclarationExpression[rVisitor
				.getVariableDeclarationExpressions().size()];
		for (int i = 0; i < variableDeclarationExpressions.length; i++) {
			variableDeclarationExpressions[i] = rVisitor.getVariableDeclarationExpressions().get(i);
		}
		return variableDeclarationExpressions;		
	}
	//end of expression getters
	
	/**
	 * returns an array that contains all the ReturnStatement AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of ReturnStatement nodes
	 */
	public static ReturnStatement[] getReturnStatements(MethodDeclaration method){
		Visitor rVisitor = new Visitor();
		method.accept(rVisitor);
		ReturnStatement[] returnStatements = new ReturnStatement[rVisitor
				.getReturnStatements().size()];
		for (int i = 0; i < returnStatements.length; i++) {
			returnStatements[i] = rVisitor.getReturnStatements().get(i);
		}
		return returnStatements;
	}
	
	/**
	 * returns an array that contains all the LineComment AST nodes in
	 * the given TypeDeclaration node
	 * 
	 * @param typeDeclaration TypeDeclaration
	 * @return an array of LineComment nodes
	 * @see org.eclipse.jdt.core.dom.LineComment
	 */
	public static LineComment[] getLineComments(TypeDeclaration typeDeclaration) {
		Visitor lcVisitor = new Visitor();
		typeDeclaration.accept(lcVisitor);
		LineComment[] lineComments = new LineComment[lcVisitor
				.getLineComments().size()];
		System.out.println("szie: "+ lcVisitor.getLineComments().size());
		for (int i = 0; i < lineComments.length; i++) {
			lineComments[i] = lcVisitor.getLineComments().get(i);
		}
		return lineComments;
	}
	
	/**
	 * returns an array that contains all the LineComment AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of LineComment nodes
	 * @see org.eclipse.jdt.core.dom.LineComment
	 */
	public static LineComment[] getLineComments(MethodDeclaration method) {
		Visitor lcVisitor = new Visitor();
		method.accept(lcVisitor);
		LineComment[] lineComments = new LineComment[lcVisitor
				.getLineComments().size()];
		for (int i = 0; i < lineComments.length; i++) {
			lineComments[i] = lcVisitor.getLineComments().get(i);
		}
		return lineComments;
	}
	
	/**
	 * returns an array that contains all the BlockComment AST nodes in
	 * the given TypeDeclaration node
	 * 
	 * @param typeDeclaration TypeDeclaration
	 * @return an array of BlockComment nodes
	 */
	public static BlockComment[] getBlockComments(TypeDeclaration typeDeclaration) {
		Visitor bcVisitor = new Visitor();
		typeDeclaration.accept(bcVisitor);
		BlockComment[] blockComments = new BlockComment[bcVisitor
				.getLineComments().size()];
		for (int i = 0; i < blockComments.length; i++) {
			blockComments[i] = bcVisitor.getBlockComments().get(i);
		}
		return blockComments;
	}
	
	/**
	 * returns an array that contains all the BlockComment AST nodes in
	 * the given MethodDeclaration node
	 * 
	 * @param method MethodDeclaration
	 * @return an array of BlockComment nodes
	 */
	public static BlockComment[] getBlockComments(MethodDeclaration method) {
		Visitor bcVisitor = new Visitor();
		method.accept(bcVisitor);
		BlockComment[] blockComments = new BlockComment[bcVisitor
				.getLineComments().size()];
		for (int i = 0; i < blockComments.length; i++) {
			blockComments[i] = bcVisitor.getBlockComments().get(i);
		}
		return blockComments;
	}
}
